package com.yuanhua.sim.gateway.utils;

/***
 * 全局唯一自增ID生成器
 * @author songguoxiang
 * @date: 2022/8/1 15:29
 */
public class IncriAndUniqueID {
    private final static int MAX_MSG_SEQ = 0xfff;
    private static int currentSeq = 0;
    public final  static  char[] arr = new char[]{'2','3','4','5','6','7','8','9','A','B','C',
            'D','E','F','G','H','J','K','L','M','N','P','Q','R','S','T','U','V','W','X','Y','Z'
    };

    public static void main(String[] args) {
        long start = System.currentTimeMillis();
        System.out.println(start);
        System.out.println(getIncriAndUniqueId(5, 8555));
        String incriAndUniqueID = getIncriAndUniqueId(5, 8555);
        int length = incriAndUniqueID.getBytes().length;
        System.out.println("占用字节===" + length);
        System.out.println(System.currentTimeMillis() - start);
    }
    public static String getIncriAndUniqueId(int type, Integer sessionId){
        //
        long highBit = System.currentTimeMillis();
        int seq = getMsgSeq();
        highBit = highBit << 12;
        highBit = highBit | seq;
        //拼接消息类型
        highBit = highBit << 4;
        highBit = highBit | (type & 0xF);
        //取会话id的低12位
        int sessionIdInt = sessionId.hashCode() & 0x3FFFFF;
        highBit = highBit << 6;
        //取高6位拼接起来
        highBit = highBit | (sessionIdInt >> 16);
        int lowBit = (sessionIdInt & 0xFFF) << 16;
        String pre = Long.toBinaryString(highBit);
        String next = Integer.toBinaryString(lowBit);
        StringBuilder sb = new StringBuilder(pre + next);
        StringBuilder rest = new StringBuilder();
        int i = 0;
        //编码
        for (int j = 0; j < 16; j++) {
            //取前五位数字
            String code = sb.substring(i, i + 5);
            char a = arr[Integer.parseInt(code,2)];
            if(j != 0 && j % 4 == 0) {
                rest.append('-');
            }
            rest.append(a);
            i += 5;
        }
        return rest.toString();
    }
    //防止相同时间戳排序问题，使用12位存储
    public synchronized static int getMsgSeq() {
        int ret = currentSeq++;
        if(ret > MAX_MSG_SEQ){
            currentSeq = 0;
            ret = currentSeq++;
        }
        return ret;

    }
}
